package cn.xiaoke.test.y22m01;

import java.util.*;

public class Reservoir<T> {

    private final static Random random = new Random();

    private final int num;
    private List<T> list;
    private int count;

    public int getNum() {
        return num;
    }

    public List<T> getList() {
        return list;
    }

    public int getCount() {
        return count;
    }

    public Reservoir(int n) {
        this.num = n;
        list = new ArrayList<>(n);
    }

    public void add(T t) {
        if (count < num) {
            list.add(t);
            count++;
        } else {
            final int rand = random.nextInt(++count);
            if (rand < num) {
                list.set(rand, t);
            }
        }
    }


//    public static void main(String[] args) {
//        final int[] ids = new int[1000];
//        for (int i = 0; i < 1000000; i++) {
//            final Reservoir<Integer> reservoir = new Reservoir<>(10);
//            for (int j = 0; j < 1000; j++) {
//                reservoir.add(j);
//            }
//            final List<Integer> list = reservoir.getList();
//            list.forEach(id -> {
//                ids[id]++;
//            });
//        }
//        System.out.println(Arrays.toString(ids));
//    }

    public static void main(String[] args) {
        final int[] ids = new int[1000];
        for (int i = 0; i < 1000000; i++) {
            Reservoir<Integer>[] reservoirs = new Reservoir[4];
            for (int j = 0; j < reservoirs.length; j++) {
                reservoirs[j] = new Reservoir<>(10);
            }
            for (int j = 0; j < ids.length; j++) {
                final int rand = random.nextInt(10000);
                if (rand < 300) {
                    reservoirs[0].add(j);
                } else if (rand < 900) {
                    reservoirs[1].add(j);
                } else if (rand < 2700) {
                    reservoirs[2].add(j);
                } else {
                    reservoirs[3].add(j);
                }
            }
            int sum = 0;
            final TreeMap<Integer, Reservoir<Integer>> treeMap = new TreeMap<>();
            for (Reservoir<Integer> reservoir : reservoirs) {
                final int count = reservoir.getCount();
                treeMap.put(sum + count, reservoir);
                sum += count;
            }
            for (int j = 0; j < 10; j++) {
                final int rand = random.nextInt(sum);
                final Map.Entry<Integer, Reservoir<Integer>> entry = treeMap.ceilingEntry(rand);
                final Reservoir<Integer> reservoir = entry.getValue();
                final List<Integer> list = reservoir.getList();
                final Integer id = list.remove(random.nextInt(list.size()));
                ids[id]++;
            }
        }
        System.out.println(Arrays.toString(ids));
    }

}
